{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day04 掌握`[]`的用法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　通过前面日程的学习，相信大家已经会运用正则表达式匹配**完全确定**（简单字符匹配）的字符，以及**完全不确定**（即用`.`来表示的任意非换行符字符），并且配合`*`与`+`，你也学会了匹配重复出现的模式。\n",
    "\n",
    "　　但是有些时候，我们需要匹配的可能是**连续的数字**譬如电话号码，也可能是所有**大写字母开头的单词**，这种情况下，我们就需要使用到今天将要带大家学习的`[]`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　首先来看上文提到过的例子：\n",
    "> 有一大段用户名与文本交替构成的字符串，现在要求我们对其中所有电话号码进行提取，就像下面的`s`一样"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = '张三：13511111111，李四：010-11111111，王五：13922222222，赵六：13300000000'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　仅凭我们先前学习到的知识，是无法实现目的的，因为这段文字中连续出现的数字就属于典型的**范围匹配**，即我们要匹配的内容为同一类型字符的连续出现，这种时候我们就需要用到`[]`。\n",
    "\n",
    "　　下面我们来学习`[]`，注意使用它时一定是成对的中括号，因为它的作用是匹配括起来的内容里各种模式中的任意一种，先忘掉前面的`s`，看看下面这个小例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['6', '7', '8', '7', '6', '7', '8', '8', '7', '8']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "s1 = '1111678762222788781111'\n",
    "\n",
    "# 匹配所有的6或7或8\n",
    "re.findall('[678]', s1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　我们在`[]`内部填写了3个普通的**单个**字符`6`、`7`和`8`，而`[]`接受到这些模式之后，帮我们从原始字符串提取出在上述3个字符串中出现过的**单个**字符，如果我们想要匹配的不是**单个**字符，而是上述3种字符任意排列形成的连续片段，就可以用到昨天学习到的`+`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['67876', '78878']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('[678]+', s1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　而`[]`最好用的功能在于其可以通过`-`符号连接两个字符串来概括中间范围内的字符，大家用过排序功能的都知道，不管是数字还是字母甚至是汉字，都是可以进行排序的，利用这个特点，我们就可以在`[]`里简短地概括范围，譬如`[0-9]`就代表从`0`到`9`的所有字符，`[a-z]`就代表从`a`到`z`的所有小写字母，`[A-Z]`就代表从`A`到`Z`的所有大写字母："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['2', '1', '3', '1', '2', '3', '2', '1', '3', '2', '1']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('[0-9]', 'adsad21312dasdas321321')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['S', 'A', 'b', 'n', 'B', 'V', 'f', 'a', 'B', 'v']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('[a-zA-Z]', '321312SAbnBVfaBv4545746')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　掌握了这个之后，我们来试着实现文章开头对电话号码的提取："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.status.idle": "2020-08-27T12:49:18.549615Z",
     "shell.execute_reply": "2020-08-27T12:49:18.549615Z",
     "shell.execute_reply.started": "2020-08-27T12:49:18.542634Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['13511111111', '010', '11111111', '13922222222', '13300000000']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('[0-9]+', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　跟我们的预期效果不同的是，这里的座机号码因为区号跟号码之间搁着一个`-`，导致匹配时被打断成两个部分，这时我们就可以把`-`也写到`[]`里，要注意`-`并不属于**元字符**，它只会在其两边出现可连接成范围的字符时发挥概括范围的作用，其他时候它就是它自己，无需像**元字符**那样用`\\`转义："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-27T12:49:18.551610Z",
     "iopub.status.busy": "2020-08-27T12:49:18.551610Z",
     "iopub.status.idle": "2020-08-27T12:49:18.559592Z",
     "shell.execute_reply": "2020-08-27T12:49:18.558601Z",
     "shell.execute_reply.started": "2020-08-27T12:49:18.551610Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['13511111111', '010-11111111', '13922222222', '13300000000']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 匹配成功~\n",
    "re.findall('[0-9-]+', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Day04 课后小测验\n",
    "\n",
    "　　相信通过上面的内容，你已经对`[]`的用法有了一定了解，百炼成钢，下面请你从给定的字符串中提取出所有**正确**的满足日期格式（XXXX-XX-XX）格式的片段："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-27T12:49:18.561583Z",
     "iopub.status.busy": "2020-08-27T12:49:18.561583Z",
     "iopub.status.idle": "2020-08-27T12:49:18.566570Z",
     "shell.execute_reply": "2020-08-27T12:49:18.565572Z",
     "shell.execute_reply.started": "2020-08-27T12:49:18.561583Z"
    }
   },
   "outputs": [],
   "source": [
    "target = '今天是-2020-08-27，天气晴，比前天（2020-08-25-）要凉快了一些。'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['2020-08-27', '2020-08-25']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('[0-9]+-[0-9]+-[0-9]+',target)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:55:19.898241Z",
     "iopub.status.busy": "2020-08-26T12:55:19.897245Z",
     "iopub.status.idle": "2020-08-26T12:55:19.904225Z",
     "shell.execute_reply": "2020-08-26T12:55:19.903227Z",
     "shell.execute_reply.started": "2020-08-26T12:55:19.898241Z"
    }
   },
   "source": [
    "　　请将你的答案截图发到本帖评论区~"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
